package vip.aster.system.controller;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import vip.aster.common.constant.CacheConstants;
import vip.aster.common.constant.Constants;
import vip.aster.common.exception.BusinessException;
import vip.aster.common.utils.CacheUtils;
import vip.aster.common.utils.PageInfo;
import vip.aster.common.utils.RSAEncrypt;
import vip.aster.common.utils.ResultInfo;
import vip.aster.framework.i18n.MessageUtils;
import vip.aster.framework.log.annotation.Log;
import vip.aster.framework.log.enums.BusinessTypeEnum;
import vip.aster.framework.security.entity.SecurityUser;
import vip.aster.framework.security.entity.UserDetail;
import vip.aster.system.entity.SysUser;
import vip.aster.system.query.SysUserQuery;
import vip.aster.system.service.SysUserPostService;
import vip.aster.system.service.SysUserRoleService;
import vip.aster.system.service.SysUserService;
import vip.aster.system.vo.SysUserPasswordVO;
import vip.aster.system.vo.SysUserVO;

import java.util.List;

/**
 * 用户管理
 *
 * @author Aster
 * @since 2023/12/12 16:27
 */
@Tag(name = "用户管理")
@RestController
@RequestMapping("/sys/user")
@AllArgsConstructor
public class SysUserController {
    private SysUserService sysUserService;
    private SysUserRoleService sysUserRoleService;
    private SysUserPostService sysUserPostService;
    private PasswordEncoder passwordEncoder;

    @GetMapping("/page")
    @Operation(summary = "分页")
    @Log(type = BusinessTypeEnum.SEARCH)
    @PreAuthorize("hasAuthority('sys:user:list')")
    public ResultInfo<PageInfo<SysUserVO>> page(@ParameterObject SysUserQuery query) {
        PageInfo<SysUserVO> page = sysUserService.pageList(query);
        return ResultInfo.success(page);
    }

    @GetMapping("/info/{userId}")
    @Operation(summary = "信息")
    @PreAuthorize("hasAuthority('sys:user:info')")
    public ResultInfo<SysUserVO> get(@PathVariable("userId") String userId) {
        SysUser entity = sysUserService.getById(userId);

        SysUserVO vo = new SysUserVO(entity);

        // 用户角色列表
        List<String> roleIdList = sysUserRoleService.getRoleIdList(userId);
        vo.setRoleIdList(roleIdList);

        // 用户岗位列表
        List<String> postIdList = sysUserPostService.getPostIdList(userId);
        vo.setPostIdList(postIdList);

        return ResultInfo.success(vo);
    }

    @GetMapping("/info")
    @Operation(summary = "登录用户")
    public ResultInfo<SysUserVO> info() {
        SysUser sysUser = sysUserService.getById(SecurityUser.getUserId());
        if (sysUser == null) {
            return ResultInfo.failed(MessageUtils.message("user.edit.id.null"));
        }
        SysUserVO user = new SysUserVO(sysUser);
        return ResultInfo.success(user);
    }

    @GetMapping("/validateUserName")
    @Operation(summary = "校验用户名")
    public ResultInfo<Boolean> validateUserName(@ParameterObject SysUserQuery query) {
        if (StrUtil.isBlank(query.getUsername())) {
            return ResultInfo.success(true);
        }
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysUser::getUsername, query.getUsername());
        if (StrUtil.isNotBlank(query.getId())) {
            queryWrapper.ne(SysUser::getId, query.getId());
        }
        long count = sysUserService.count(queryWrapper);
        return ResultInfo.success(count > 0 ? false : true);
    }

    @PostMapping("/edit")
    @Operation(summary = "修改")
    @Log(type = BusinessTypeEnum.SAVE)
    @PreAuthorize("hasAnyAuthority('sys:user:edit')")
    public ResultInfo<String> editInfo(@RequestBody @Valid SysUserVO vo) {
        // id不能为空
        if (StrUtil.isBlank(vo.getId())) {
            ResultInfo.failed(MessageUtils.message("user.edit.id.null"));
        }

        // 保存
        sysUserService.editInfo(vo);

        return ResultInfo.success();
    }

    @PostMapping("/password")
    @Operation(summary = "修改密码")
    @Log(type = BusinessTypeEnum.UPDATE)
    public ResultInfo<String> password(@RequestBody @Valid SysUserPasswordVO vo) {
        UserDetail user = SecurityUser.getUser();
        assert user != null;

        // 解密密码
        String privateKey = CacheUtils.get(CacheConstants.SECRET_KEY, CacheConstants.PRIVATE_KEY, String.class);
        String newPassword;
        try {
            String oldPassword = RSAEncrypt.decrypt(vo.getOldPassword(), privateKey);
            newPassword = RSAEncrypt.decrypt(vo.getNewPassword(), privateKey);
            if (!passwordEncoder.matches(oldPassword, user.getPassword())) {
                return ResultInfo.failed(MessageUtils.message("user.password.old.error"));
            }
            if (newPassword.length() < 4 || newPassword.length() > 20) {
                return ResultInfo.failed(MessageUtils.message("user.password.length"));
            }
        } catch (Exception e) {
            throw new BusinessException(MessageUtils.message("auth.login.decrypt.error"));
        }

        // 修改密码
        sysUserService.updatePassword(user.getId(), passwordEncoder.encode(newPassword));

        return ResultInfo.success();
    }

    @PostMapping("/save")
    @Operation(summary = "保存")
    @Log(type = BusinessTypeEnum.SAVE)
    @PreAuthorize("hasAnyAuthority('sys:user:add', 'sys:user:edit')")
    public ResultInfo<String> save(@RequestBody @Valid SysUserVO vo) {
        // 新增密码不能为空
        if (StrUtil.isBlank(vo.getId()) && StrUtil.isBlank(vo.getPassword())) {
            ResultInfo.failed(MessageUtils.message("user.password.empty"));
        }

        // 如果密码不为空，则进行加密处理
        if (StrUtil.isBlank(vo.getPassword())) {
            vo.setPassword(null);
        } else {
            vo.setPassword(passwordEncoder.encode(vo.getPassword()));
        }

        // 保存
        sysUserService.save(vo);

        return ResultInfo.success();
    }

    @PostMapping("/delete")
    @Operation(summary = "删除")
    @Log(type = BusinessTypeEnum.DELETE)
    @PreAuthorize("hasAuthority('sys:user:delete')")
    public ResultInfo<String> delete(@RequestBody List<String> idList) {
        String userId = SecurityUser.getUserId();
        if (idList.contains(userId)) {
            return ResultInfo.failed(MessageUtils.message("user.delete.current"));
        }

        sysUserService.delete(idList);

        return ResultInfo.success();
    }

    @PostMapping("/import")
    @Operation(summary = "导入用户")
    @Log(type = BusinessTypeEnum.IMPORT)
    @PreAuthorize("hasAuthority('sys:user:import')")
    public ResultInfo<String> importExcel(@RequestParam("file") MultipartFile file) {
        if (file.isEmpty()) {
            return ResultInfo.failed(MessageUtils.message("user.import.empty"));
        }
        sysUserService.importByExcel(file, passwordEncoder.encode(Constants.DEFAULT_PASSWORD));

        return ResultInfo.success();
    }

    @PostMapping("/export")
    @Operation(summary = "导出用户")
    @Log(type = BusinessTypeEnum.EXPORT)
    @PreAuthorize("hasAuthority('sys:user:export')")
    public void export() {
        sysUserService.export();
    }
}
